(function(window, angular){
    'use strict';
    (function(){
        'use strict';
        var module = angular.module('sMESUpdate',['ng']);

        module.service('CommonService', ['config', function(config){
            this.server_name = {
                '209':{ 'Production':'MobileMiddleware', 'Test':'MobileMiddleware_Test' },
                '2010':{ 'Production':'SMES_Production_MESws_STD', 'Test':'SMES_Test_MESws_STD' },
                '210':{ 'Production':'SMES_Production_Services', 'Test':'SMES_Test_Services' },
            };
			
			this.CheckMiniVersion = (version)=>{
				//更新器可被更新的最低版本
				var _mini_version = '3.3.1.2021110401';
				//patch 檔的version
				return GetRealVersion(version) > _mini_version;
			}
			
			this.BackupFile = (...path)=>{
				try{
					//window.nodeRequire('fs').copyFileSync(path, path + '.bak', window.nodeRequire('fs').constants.COPYFILE_FICLONE_FORCE);
					return new Promise((resolve)=>{
						BackupFileImp(0, path, resolve);
					});
				}catch(e){
					console.error(e);
				}
			}
			
			this.RestoreFile = (...path)=>{
				try{
					//window.nodeRequire('fs').copyFileSync(path + '.bak', window.nodeRequire('fs').constants.COPYFILE_FICLONE_FORCE);
					return new Promise((resolve)=>{
						RestoreFileImp(0, path, resolve);
					});
				}catch(e){
					console.error(e);
				}
			}
			
			function GetRealVersion(version){
				let _a_version = version.split('.');
				return _a_version[0]+'.'+_a_version[1]+'.'+_a_version[2]+'.'+_a_version[_a_version.length-1];
			}
			
			function BackupFileImp(index, paths, callback) {
				if(index < paths.length){
					copyFile(paths[index], paths[index] + '.bak').then(()=>{
						index++;
						BackupFileImp(index, paths, callback);
					});
				} else if(callback){
					callback();
				}
			}
			
			function RestoreFileImp(index, paths, callback) {
				if(index < paths.length){
					copyFile(paths[index] + '.bak', paths[index]).then(()=>{
						index++;
						RestoreFileImp(index, paths, callback);
					});
				} else if(callback){
					callback();
				}
			}
			
			function copyFile(source, target) {
			  var rd = window.nodeRequire('fs').createReadStream(source);
			  var wr = window.nodeRequire('fs').createWriteStream(target);
			  try {
				return new Promise(function(resolve, reject) {
				  rd.on('error', reject);
				  wr.on('error', reject);
				  wr.on('finish', resolve);
				  rd.pipe(wr);
				});
			  } catch (error) {
				rd.destroy();
				wr.end();
				throw error;
			  }
			}
        }]);

        //Communication with Server
        module.service('HttpService', ['$http', '$filter', '$translate', 'config', 'CommonService',
            function($http, $filter, $translate, config, $CommonService){
                var service = this;
                function prepareSend(sendData){
                    var data = {
                        method : 'POST',
                        headers : {
                            'Content-Type': 'application/json;charset=UTF-8'
                        },
                        data : {}
                    };
                    if(config.server.timeout != 0)
                        data.timeout =config.server.timeout;

                    var name = sendData.name||config.server.name;
                    var ip = sendData.ip||config.server.ip;
                    var port = sendData.port||config.server.port;
                    if(sendData.version == '209'){
                        if(config.setting.ssl)
                            data.url = 'https://' + ip + ':'+ port + '/'+ name +'/api/v1/transaction/json';
                        else
                            data.url = 'http://' + ip + ':'+ port + '/'+ name +'/api/v1/transaction/json';
                        data.data = {
                            applicationId:config.applicationId,
                            uri: 'SMES_Update',
                            headers:{
                                Method : 'SMES_Update',
                                'mds.userid' : '',
                                'mds.password': '',
                                'mds.environment': config.setting.environment,
                                'mds.language_mode': $translate.use(),
                                'mds.computer_name': 'Client',
                                'mds.sessionno':  ''
                            },
                            cookies:[],
                            content:JSON.stringify(angular.merge({
                                CompanyID:config.setting.companyId,
                                Equipment:''
                            }, data.content))
                        };
                    } else if(sendData.version == '2010'){
                        if(config.setting.ssl)
                            data.url = 'https://' + ip + ':'+ port + '/'+ name +'/wsInvoke.asmx/invokeSrv';
                        else
                            data.url = 'http://' + ip + ':'+ port + '/'+ name +'/wsInvoke.asmx/invokeSrv';

                        data.data = {
                            method:'tcSMES_LiveUpdate.clsLiveUpdate.LiveUpdate',
                            parameters:['{}']
                        };
                    } else {
                        if(config.setting.ssl)
                            data.url = 'https://' + ip + ':'+ port + '/'+ name +'/InvokeJSON';
                        else
                            data.url = 'http://' + ip + ':'+ port + '/'+ name +'/InvokeJSON';
                        data.data.header = {
                            method : 'ServicesSTD.Module_SYS.live_update',
                            lang : $translate.use(),
                            is_debug : true,
                            account : '',
                            password : '',
                            version : '',
                            mac : '',
                            session : '',
                        };
                        data.data.content = sendData.content;
                    }
                    return data;
                }

				//取得更新資訊
                service.send = function(sendData){
                    $http(prepareSend(sendData)).success(function(data, status, headers, config) {
                        if(sendData.version == '209'){
                            AfterSend_209(sendData, data, status, headers, config);
                        } else if(sendData.version == '2010'){
                            AfterSend_2010(sendData, data, status, headers, config);
                        }  else {
                            AfterSend_210(sendData, data, status, headers, config);
                        }
                    }).error(function(respose,status_code){
                        status_code = status_code+'';
                        if(status_code.indexOf('5') == 0){
                            $CommonService.writeLog(status_code + $filter('translate')('error.status_code_5'));
                        } else if(status_code.indexOf('4') == 0){
                            $CommonService.writeLog(status_code + $filter('translate')('error.status_code_4'));
                        } else {
                            if(respose && respose.Message){
                                $CommonService.writeLog(status_code + ' : '+ respose.message);
                            } else {
                                $CommonService.writeLog(status_code + ' : '+ $filter('translate')('error.connectRefused'));
                            }
                        }
                        $CommonService.changeMode('setting');
                    });
                };

                function AfterSend_209(sendData, data){
                    try{
                        var contentData = JSON.parse(data.content);
                        if(contentData.IsSuccess){
                            if(sendData.success)
                                sendData.success(JSON.parse(contentData.Result));
                        } else {
                            if(sendData.error){
                                sendData.error(contentData);
                            } else {
                                $CommonService.writeLog(contentData.SysException);
                                $CommonService.changeMode('setting');
                            }
                        }
                    }catch(e){
                        $CommonService.writeLog(e);
                        $CommonService.changeMode('setting');
                    }
                }

                function AfterSend_2010(sendData, data){
                    var contentData;
                    try{
                        contentData = JSON.parse(data.d);
                    } catch(e){
                        $CommonService.writeLog('Can\'t parse content : ' + data.d);
                        $CommonService.changeMode('setting');
                    }
                    if(contentData){
                        try{
                            if(contentData.Code === '0' || contentData.Code === null){
                                if(sendData.success)
                                    sendData.success(JSON.parse(contentData.ResultJson));
                            }else {
                                if(sendData.error){
                                    sendData.error(contentData);
                                } else {
                                    $CommonService.writeLog(contentData.Exception);
                                    $CommonService.changeMode('setting');
                                }
                            }
                        } catch(e){
                            $CommonService.writeLog(e);
                            $CommonService.changeMode('setting');
                        }
                    }
                }

                function AfterSend_210(sendData, data){
                    try{
                        if(data.isSuccess){
                            if(sendData.success)
                                sendData.success(data.Content, data);
                        } else {
                            if(sendData.error){
                                sendData.error(data);
                            } else {
                                $CommonService.writeLog(data.Message);
                                $CommonService.changeMode('setting');
                            }
                        }
                    } catch(e){
                        $CommonService.writeLog(e);
                        $CommonService.changeMode('setting');
                    }
                }
            }
        ]);
        //Update Client
        module.service('UpdateService',['$filter','CommonService', 'config',
            function($filter, $CommonService, config){
                var service = this;
                //service.updateInfo;

                //檢查是否需要重新下載更新
                service.checkUpdateExist = function(callback){
                    if(window.cordova && window.resolveLocalFileSystemURL){
                        window.resolveLocalFileSystemURL(window.cordova.file.dataDirectory+'update',
                            function(updateFolder){
                                //存在
                                if(callback)
                                    callback(true);
                            },
                            function(){
                                //不存在
                                if(callback)
                                    callback(false);
                            }
                        );
                    } else{
                        //20181004 modify by dustdusk for M#: 增加檢核更新檔是否存在
                        if(config.file_appVersion != config.appVersion){
                            if(callback)
                                callback(false);
                        } else {
                            if(callback)
                                callback(true);
                        }

                    }
                };

                //檢查模組資料夾是否存在
                service.checkModuleExist = function(name){
                    if(window.nodeRequire){
                        var root_path = '';
                        if($CommonService.platform == 'electron'){
                            // 20240321 modify by Alan for#159805 : electron升級後，兼容新舊版本
                            const remote = window.nodeRequire('electron').remote || window.nodeRequire('@electron/remote');
                            root_path = remote.app.getAppPath()+'\\';
                        } else {
                            root_path = window.nodeRequire('path').dirname(process.execPath)+'\\package.nw\\';
                        }
                        return window.nodeRequire('fs').existsSync(root_path+'\\www\\module\\'+name);
                    } else{
                        return true;
                    }
                };

                service.downloadUpdate = function(updateInfo){
                    var downloadUpdate, downloadModule;
                    $CommonService.writeLog($filter('translate')('update.msg.update_start'));//開始準備更新...
                    if(window.cordova != undefined){
                        updateInfo.root_path = cordova.file.dataDirectory;
                        downloadUpdate = downloadUpdateforMobile;
                        downloadModule = function(){
                            downloadModuleforMobile({
                                root_path:updateInfo.root_path,
                                module_details:updateInfo.module_details||[],
                                callback:function(){
                                    downloadBackground(updateInfo, function(){
                                        // 20231227 modify by Alan for M#154732 : 安卓更新後跳轉到正確的頁面
                                        const platform = (device && device.platform) || '';
                                        if (platform === 'Android') {
                                            $CommonService.reDirect(updateInfo.root_path + 'update/index.html');
                                        } else {
                                            $CommonService.reDirect('index.html');
                                        }
                                    });
                                }
                            });
                        };
                    } else if(window.nodeRequire){
                        if($CommonService.platform == 'electron'){
                            // 20240321 modify by Alan for#159805 : electron升級後，兼容新舊版本
                            const remote = window.nodeRequire('electron').remote || window.nodeRequire('@electron/remote');
                            updateInfo.root_path = remote.app.getAppPath()+'\\';
                        } else {
                            updateInfo.root_path = nodeRequire('path').dirname(process.execPath)+'\\package.nw\\';
                        }
                        downloadUpdate = downloadUpdateForWin;
                        downloadModule = function(){
                            downloadModuleforWin({
                                root_path:updateInfo.root_path,
                                module_details:updateInfo.module_details||[],
                                callback:function(){
                                    downloadBackground(updateInfo, function(){
                                        $CommonService.reDirect('index.html');
                                    });
                                }
                            });
                        };
                    } else {
                        document.location.href = 'index.html';
                        return;
                    }

                    if(updateInfo.need_update){
                        downloadUpdate(updateInfo, downloadModule);
                    } else {
                        downloadModule();
                    }
                };

                //20181003 add by Dustdusk for M#:模組更新功能
				//download module update pathc file
                function downloadModuleforWin(options){
                    var downloadModule = function(index, next){
                        var module = options.module_details[index];
                        if(module != undefined){
                            if(module.url != undefined){
                                downloadZIPforWin({
                                    name:$filter('translate')('update.msg.module_version')+module.name,
                                    url: module.url,
                                    temp_path: options.root_path + module.name+'.zip',
                                    dest_path: options.root_path + '\\www\\module\\'+module.name+'\\',
									backup:()=>{
										if(!$CommonService.CheckMiniVersion(module.version)){
											return $CommonService.BackupFile(
												options.root_path+'www\\module\\system\\program\\update\\startup.js',
												options.root_path+'www\\module\\system\\program\\update\\update.js');
										} else {
											return new Promise((resolve)=>{
												if(resolve)
													resolve();
											});
										}
									},
									restore:()=>{
										if(!$CommonService.CheckMiniVersion(module.version)){
											return $CommonService.RestoreFile(
												options.root_path+'www\\module\\system\\program\\update\\startup.js',
												options.root_path+'www\\module\\system\\program\\update\\update.js');
										} else {
											return new Promise((resolve)=>{
												if(resolve)
													resolve();
											});
										}
									},
                                    callback: function(){
                                        next(++index, next);
                                    }
                                });
                            } else {
                                next(++index, next);
                            }
                        } else if(options.callback){
                            options.callback();
                        }
                    };
                    downloadModule(0, downloadModule);
                }

                //20181003 add by Dustdusk for M#:模組更新功能
                function downloadModuleforMobile(options){
                    var downloadModule = function(index, next){
                        var module = options.module_details[index];
                        if(module != undefined){
                            if(module.url != undefined){
                                var module_file = options.root_path + module.name+'.zip';
                                downloadZIPforMobile({
                                    name:$filter('translate')('update.msg.module_version')+module.name,
                                    url: module.url,
                                    temp_path: module_file,
                                    callback: function(){
                                        unZIPforMobile({
                                            name:$filter('translate')('update.msg.module_version')+module.name,
                                            src_path:module_file,
                                            dest_path:options.root_path+'update/module/'+module.name,
                                            callback:function(){
                                                clearUpdate(options.root_path, module.name+'.zip', function(){
                                                    next(++index, next);
                                                });
                                            }
                                        });
                                    }
                                });
                            } else {
                                next(++index, next);
                            }
                        } else if(options.callback){
                            options.callback();
                        }
                    };
                    downloadModule(0, downloadModule);
                }

                //20180920 add by Dustdusk for M#:背景圖更新功能
                function downloadBackground(updateInfo, callback){
                    if(updateInfo.backgroundurl != undefined && updateInfo.backgroundurl != ''){
                        var background_download_url = $CommonService.download_root_path + '/' + updateInfo.backgroundurl;
                        if(window.nodeRequire){
                            var AppPath;
                            if($CommonService.platform == 'electron'){
                                // 20240321 modify by Alan for#159805 : electron升級後，兼容新舊版本
                                const remote = window.nodeRequire('electron').remote || window.nodeRequire('@electron/remote');
                                AppPath = remote.app.getAppPath()+'\\';
                            } else {
                                var nwDir = window.nodeRequire('path').dirname(process.execPath);
                                AppPath = nwDir+'\\package.nw\\';
                            }
                            var tempFile = window.nodeRequire('fs').createWriteStream(AppPath + 'www\\image\\BG-01.jpg');
                            tempFile.on('finish', function(){
                                tempFile.close(function(){
                                    try{
                                        $CommonService.writeLog($filter('translate')('update.msg.background_updating'));//背景圖更新中...
                                        callback(updateInfo);
                                    }catch(e){
                                        $CommonService.writeLog($filter('translate')('update.msg.background_cant_download')+'<br>'+e);//無法下載背景圖，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                                        $CommonService.changeMode('setting');
                                    }
                                });
                            });
                            var request = window.nodeRequire('request')(background_download_url, function(error, response, body){
                                if(error){
                                    $CommonService.writeLog($filter('translate')('update.msg.background_cant_download')+'<br>'+error);//無法下載背景圖，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                                    $CommonService.changeMode('setting');
                                } else {
                                    $CommonService.writeLog($filter('translate')('update.msg.background_downloading')+'100%');
                                }
                            });
                            request.pipe(tempFile);
                            window.nodeRequire('request-progress')(request, {throttle: 200})
                            .on('progress', function (state) {
                                //背景圖下載中...%
                                $CommonService.writeLog($filter('translate')('update.msg.background_downloading') + (Math.round(state.percent * 100))+'%');//背景圖下載中...%
                            })
                            .on('error', function (err) {
                                $CommonService.writeLog($filter('translate')('update.msg.background_cant_download')+'<br>'+err);//無法下載背景圖，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                                $CommonService.changeMode('setting');
                            });
                        } else if(window.cordova){
                            var zipDistUrl = window.cordova.file.dataDirectory+'update/';
                            var ft = new window.FileTransfer();
                            ft.onprogress = function(progressEvent) {
                                if (progressEvent.lengthComputable) {
                                    //背景圖下載中...%
                                    $CommonService.writeLog($filter('translate')('update.msg.background_downloading')+Math.floor(progressEvent.loaded / progressEvent.total * 100)+'%');
                                }
                            };
                            ft.download(background_download_url, zipDistUrl+'image/BG-01.jpg',
                                function(r) {
                                    $CommonService.writeLog($filter('translate')('update.msg.update', {name:''}));//更新中...
                                    callback(updateInfo);
                                }, function(error) {
                                    $CommonService.writeLog($filter('translate')('update.msg.background_cant_download'));//無法下載背景圖，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                                    $CommonService.changeMode('setting');
                                }
                            );
                        } else {
                            callback(updateInfo);
                        }
                    } else {
                        callback(updateInfo);
                    }
                }

				//下載更新檔
				//download update pathc file
                function downloadUpdateForWin(updateInfo, callback){
                    downloadZIPforWin({
                        name:$filter('translate')('update.msg.std_version'),
                        url: updateInfo.url,
                        temp_path: updateInfo.root_path+'update.zip',
                        dest_path: updateInfo.root_path+'www\\',
						backup:()=>{
							if(!$CommonService.CheckMiniVersion(updateInfo.version)){
								return $CommonService.BackupFile(
									updateInfo.root_path+'www\\startup.html', 
									updateInfo.root_path+'www\\module\\system\\program\\update\\startup.js',
									updateInfo.root_path+'www\\module\\system\\program\\update\\update.js');
							} else {
								return new Promise((resolve)=>{
									if(resolve)
										resolve();
								});
							}
						},
						restore:()=>{
							if(!$CommonService.CheckMiniVersion(updateInfo.version)){
								return $CommonService.RestoreFile(
									updateInfo.root_path+'www\\startup.html', 
									updateInfo.root_path+'www\\module\\system\\program\\update\\startup.js',
									updateInfo.root_path+'www\\module\\system\\program\\update\\update.js');
							} else {
								return new Promise((resolve)=>{
									if(resolve)
										resolve();
								});
							}
						},
                        callback: callback
                    });
                }

                //download ZIP file with temp_path and UnZIP file to dest_path
                function downloadZIPforWin(options){
                    $CommonService.writeLog($filter('translate')('update.msg.update_download_start', options));//{{name}}開始更新...
                    var request = nodeRequire('request'),
                        progress = nodeRequire('request-progress'),
                        fs = nodeRequire('fs'),
                        Zip = nodeRequire('adm-zip-electron');

                    var tempFile = fs.createWriteStream(options.temp_path);
                    tempFile.on('finish', function(){
                        tempFile.close(function(){
                            try{
								let _unzip = ()=>{
									$CommonService.writeLog($filter('translate')('update.msg.update', options));//{{name}}更新中...
									var zip = new Zip(options.temp_path);
									zip.extractAllTo(options.dest_path, true);
									fs.unlink(options.temp_path, function(error){
										//20201207 增加restore hook function
										let _callback = ()=>{
											if(options.callback)
												options.callback();
										}
										if(typeof(options.restore) === 'function'){
											options.restore().then(_callback);
										} else if(options.callback){
											options.callback();
										}
									});
								};
								//20201207 增加backup hook function
								if(typeof(options.backup) === 'function'){
									options.backup().then(_unzip);
								} else {
									_unzip();
								}
                            }catch(e){
                                //20190718 modify by Dustdusk for M#60156: 版本更新失敗時，需要在錯誤訊息內明確告知是哪個模組更新失敗
                                $CommonService.writeLog(options.name +"："+ $filter('translate')('update.msg.zip_cant_download')+'<br>'+e);//無法下載更新，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                                $CommonService.changeMode('setting');
                            }
                        });
                    });

                    var request_instance = request(options.url, function(error, response, body){
                        if(error){
                            $CommonService.writeLog($filter('translate')('update.msg.zip_cant_download')+'<br>'+error);//無法下載更新，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                            $CommonService.changeMode('setting');
                        } else {
                            $CommonService.writeLog($filter('translate')('update.msg.update_download', options)+'100%');
                        }
                    });
                    request_instance.pipe(tempFile);
                    progress(request_instance, {
                        throttle: 200,                    // Throttle the progress event to 2000ms, defaults to 1000ms
                        // delay: 1000,                       // Only start to emit after 1000ms delay, defaults to 0ms
                        // lengthHeader: 'x-transfer-length'  // Length header to use, defaults to content-length
                    })
                    .on('progress', function (state) {
                        $CommonService.writeLog($filter('translate')('update.msg.update_download', options)+(Math.round(state.percent * 100))+'%');//{{name}}下載中...
                    })
                    .on('error', function (err) {
                        //20190718 modify by Dustdusk for M#60156: 版本更新失敗時，需要在錯誤訊息內明確告知是哪個模組更新失敗
                        $CommonService.writeLog(options.name +"："+ $filter('translate')('update.msg.zip_cant_download')+'<br>'+err);//無法下載更新，更新用的檔案不存在，請確認伺服器連線資訊是否正確
                        $CommonService.changeMode('setting');
                    });
                }

                function downloadUpdateforMobile(updateInfo, callback){
                    var afterPrepare = function(){
                            unZIPforMobile({
                                name:$filter('translate')('update.msg.std_version'),
                                src_path:updateInfo.root_path+'update.zip',
                                dest_path:updateInfo.root_path+'update',
                                callback:function(){
                                    clearUpdate(updateInfo.root_path, 'update.zip', callback);
                                }
                            });
                        };
                    downloadZIPforMobile({
                        name:$filter('translate')('update.msg.std_version'),
                        url: updateInfo.url,
                        temp_path: updateInfo.root_path+'update.zip',
                        callback: function(){
                            if(navigator.userAgent.match(/iPhone|iPad|iPod/i)){
                                prepareUnZipforIOS(updateInfo.root_path, afterPrepare);
                            } else {
                                prepareUnZipforAndroid(updateInfo.root_path, afterPrepare);
                            }
                        }
                    });
                }

                function downloadZIPforMobile(options){
                    var ft = new window.FileTransfer();
                    ft.onprogress = function(progressEvent) {
                        if (progressEvent.lengthComputable) {
                            //更新下載中
                            $CommonService.writeLog($filter('translate')('update.msg.update_download', options)+Math.floor(progressEvent.loaded / progressEvent.total * 100)+'%');//{{name}}下載中...
                        }
                    };
                    ft.download(options.url, options.temp_path,
                        function(response) {
                            $CommonService.writeLog($filter('translate')('update.msg.update', options));//{{name}}更新中...",
                            if(options.callback)
                                options.callback();
                        }, function(error) {
                            //20190718 modify by Dustdusk for M#60156: 版本更新失敗時，需要在錯誤訊息內明確告知是哪個模組更新失敗
                            $CommonService.writeLog(options.name + "："+ $filter('translate')('update.msg.cant_download'));//無法下載更新，請確認伺服器連線是否正常;
                            $CommonService.changeMode('setting');
                        }
                    );
                }

                function prepareUnZipforAndroid(root_path, callback){
                    //root_path : zip檔要複製過去的資料夾
                    var srcUrl = cordova.file.applicationDirectory + 'www/';
                    window.resolveLocalFileSystemURL(srcUrl,
                        function(directoryEntry){
                            window.resolveLocalFileSystemURL(root_path, function(dstDirectoryEntry){
                                //取得root_path內的Update資料夾，不存在則建立
                                dstDirectoryEntry.getDirectory('update', {create: true}, function(updateDirEntry){
                                    $CommonService.writeLog($filter('translate')('update.msg.prepare_updat')); //正在準備更新用的檔案...
                                    //get file cordova.js, cordova_plugins.js, plugins
                                    var cordova_files = ['cordova.js', 'cordova_plugins.js', 'cordova_plugins.js'],
                                        cordova_directorys = ['plugins', 'cordova-js-src', 'scripts'];
                                    copyfiles(directoryEntry, cordova_files, updateDirEntry, function(){
                                        copyDirectorys(directoryEntry, cordova_directorys, updateDirEntry, function(){
                                            if(callback)
                                                callback();
                                        }, getDirectoryError);
                                    }, getDirectoryError);
                                }, getDirectoryError);
                            }, getDirectoryError);
                        }, getDirectoryError
                    );
                }

                function copyfiles(src_directory, file_names, dest_directory, callback, errorback){
                    var copyfile_R = function(index, next){
                        var file_name = file_names[index];
                        if(file_name != undefined){
                            copyfile(src_directory, file_name, dest_directory, function(){
                                next(++index, next);
                            }, errorback);
                        } else {
                            callback();
                        }
                    };
                    copyfile_R(0, copyfile_R);
                }

                function copyfile(src_directory, file_name, dest_directory, callback, errorback){
                    src_directory.getFile(file_name, {}, function (fileEntry) {
                        //copy cordova.js
                        fileEntry.copyTo(dest_directory,file_name, function(){
                            callback();
                        }, function(error){
                            if(error.code == 9 || error.code == 12){
                                callback();
                            } else {
                                $CommonService.writeLog($filter('translate')('update.msg.temp_file_cant_dele')+':'+error.code);//暫存檔案刪除失敗，請重新下載
                                $CommonService.changeMode('setting');
                            }
                        });
                    }, errorback);
                }

                function copyDirectorys(src_directory, directory_names, dest_directory, callback, errorback){
                    var copyDirectory_R = function(index, next){
                        var directory_name = directory_names[index];
                        if(directory_name != undefined){
                            copyDirectory(src_directory, directory_name, dest_directory, function(){
                                next(++index, next);
                            }, errorback);
                        } else {
                            callback();
                        }
                    };
                    copyDirectory_R(0, copyDirectory_R);
                }

                function copyDirectory(src_directory, directory_name, dest_directory, callback, errorback){
                    src_directory.getDirectory(directory_name, {}, function(directoryEntry){
                        directoryEntry.copyTo(dest_directory, directory_name, function(){
                            callback();
                        }, function(error){
                            if(error.code == 9 || error.code == 12){
                                callback();
                            } else {
                                $CommonService.writeLog($filter('translate')('update.msg.temp_file_cant_dele')+':'+error.code);//暫存檔案刪除失敗，請重新下載
                                $CommonService.changeMode('setting');
                            }
                        });
                    }, errorback);
                }

                function prepareUnZipforIOS(root_path, callback){
                    var srcUrl = cordova.file.applicationDirectory + 'www/';
                    var dstDir = root_path + 'update';
                    window.resolveLocalFileSystemURL(
                            srcUrl,
                        function(directoryEntry){
                            window.resolveLocalFileSystemURL(root_path, function(dstDirectoryEntry){
                                $CommonService.writeLog($filter('translate')('update.msg.prepare_updat')); //正在準備更新用的檔案...
                                directoryEntry.copyTo(dstDirectoryEntry, 'update', function(){
                                    callback();
                                }, function(error){
                                    if(error.code == 9 || error.code == 12){
                                        //表示已經複製過了，先刪除再複製
                                        $CommonService.writeLog($filter('translate')('update.msg.delete_temp_file'));//正在刪除暫存檔案...
                                        window.resolveLocalFileSystemURL(dstDir, function(dstDirectory){
                                            dstDirectory.removeRecursively(function(){
                                                prepareUnZipforIOS(root_path, callback);
                                            },function(error){
                                                $CommonService.writeLog($filter('translate')('update.msg.temp_file_cant_dele'));//暫存檔案刪除失敗，請重新下載
                                                $CommonService.changeMode('setting');
                                            });
                                        }, getDirectoryError);
                                    } else {
                                        $CommonService.writeLog($filter('translate')('update.msg.temp_file_cant_dele')+':'+error.code);//暫存檔案刪除失敗，請重新下載
                                        $CommonService.changeMode('setting');
                                    }
                                });
                            }, getDirectoryError);

                        },
                        getDirectoryError
                    );
                }

                function getDirectoryError(error){
                    $CommonService.writeLog('ERROR'+':'+error.code);//暫存檔案刪除失敗，請重新下載
                    $CommonService.changeMode('setting');
                }

                //options.src_path:zip, options.dest_path:目標資料夾
                function unZIPforMobile(options){
                    $CommonService.writeLog($filter('translate')('update.msg.update', options));//{{name}}更新中...,
                    window.zip.unzip(options.src_path, options.dest_path,
                        function(result){
                            if(result==0){
                                options.callback();
                            } else {
                                //20190718 modify by Dustdusk for M#60156: 版本更新失敗時，需要在錯誤訊息內明確告知是哪個模組更新失敗
                                $CommonService.writeLog(options.name+"："+$filter('translate')('update.msg.zip_server_connect'));//'更新檔解析失敗，請重新下載';
                                $CommonService.changeMode('setting');
                            }
                        },
                        function(progressEvent){
                            $CommonService.writeLog($filter('translate')('update.msg.update', options) + Math.round((progressEvent.loaded / progressEvent.total) * 100)+'%');//{{name}}更新中...,
                        }
                    );
                }

                //delete update.zip file
                function clearUpdate(url, fileName, feedback){
                    try{
                        window.resolveLocalFileSystemURL(url, function(dir) {
                            dir.getFile(fileName, {create:false}, function(fileEntry) {
                                fileEntry.remove(function(){
                                    if(feedback)
                                        feedback();
                                    // The file has been removed succesfully
                                },function(error){
                                    $CommonService.writeLog($filter('translate')('update.msg.temp_file_cant_dele'));//暫存檔案刪除失敗
                                    if(feedback)
                                        feedback();
                                },function(){
                                    $CommonService.writeLog($filter('translate')('update.msg.temp_file_not_exist'));//暫存檔案不存在
                                    if(feedback)
                                        feedback();
                                });
                            });
                        });
                    } catch(e){
                        console.error(e);
                    }
                }
            }
        ]);
    })();
})(window, window.angular);
